#include <stdio.h>
#include <signal.h>
#include <arpa/inet.h>
#include <time.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
#include "insam_func.h"
//#include <sys/types.h>
//#include <sys/stat.h>

int main(int argc,char** argv)
{
	int listen_fd, client_fd;
	socklen_t addrlen;
	struct sockaddr_in client_addr, server_addr;

	printf("Insam Server Start!!\n");

	if((listen_fd = socket(AF_INET,SOCK_STREAM,0))<0){
		return 1;
	}

	memset((void*)&server_addr,0x00,sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	server_addr.sin_port = htons(PORTNUM);
	
	if(bind(listen_fd, (struct sockaddr*)&server_addr,sizeof(server_addr))==-1){
		perror("bind error\n");
		return 1;
	}

	if(listen(listen_fd,5) == -1){
		perror("listen error\n");
		return 1;
	}
	signal(SIGCHLD, SIG_IGN);

	freePort(NULL);

	while(1)
	{
		addrlen = sizeof(client_addr);
		client_fd = accept(listen_fd, (struct sockaddr*)&client_addr, &addrlen);
		if(client_fd == -1){
			perror("accept error\n");
			break;
		}

		pid_t pid = fork();
		if(pid == 0)
		{
			BYTE buf[MAXBUFF_LEN];
			memset(buf,0x00,MAXBUFF_LEN);
			int req_len = read(client_fd, buf, MAXBUFF_LEN);
			hexLog("RECEIVE MSG", buf, req_len, &client_addr);

			if(req_len > 0) {
				BYTE svn_code=0;
				int res_len=0;
				memcpy(&svn_code, buf, sizeof(svn_code));
				printf("receive svc code:%d\n", svn_code);

				BYTE* msg_buf = buf+sizeof(svn_code);

				switch(svn_code){
					case 1:
						res_len = login_process(msg_buf, &client_addr);
						int len = write(client_fd, msg_buf, res_len);
						hexLog("SEND MSG", msg_buf, res_len, &client_addr);
						if(res_len != len)
							printLog(&client_addr, "send wong msg(o:%d, w:%d)", res_len, len);
						break;
					case 2:
						res_len = logout_process(msg_buf, &client_addr);
						break;
				}
			}
			close(client_fd);
			return 0;
		} else if(pid > 0) {
			close(client_fd);
		}

	}
	return 0;
}

void printLog(struct sockaddr_in *client, const char *fmt, ...) {
	va_list argptr;
	char buf[MAXBUFF_LEN];

	va_start(argptr, fmt);
	vsprintf(buf, fmt, argptr);
	va_end(argptr);

	silentLog(client, buf);
	printf("%s\n", buf);
}

void silentLog(struct sockaddr_in *client, char *str) {
	time_t     tm_time;
	struct tm *st_time;
	char       stime[20];
	time(&tm_time);
	st_time = localtime(&tm_time);
	strftime(stime, 20, "%Y%m%d-%0H%0M%0S", st_time);

	FILE* fp = fopen("insam_server.log","a");
	fprintf(fp, "[%s]", stime);
	if(client!=NULL)
		fprintf(fp,"(from %s:%d)", inet_ntoa(client->sin_addr), client->sin_port);

	fprintf(fp, " :%s\n", str);
	fclose(fp);
}

void hexLog(char *tag, BYTE *data, int len, struct sockaddr_in *client) {
	time_t     tm_time;
	struct tm *st_time;
	char       stime[20];
	time(&tm_time);
	st_time = localtime(&tm_time);
	strftime(stime, 20, "%Y%m%d-%0H%0M%0S", st_time);

	FILE* fp = fopen("insam_server.log","a");

	fprintf(fp, "[%s]", stime);
	if(client!=0)
		fprintf(fp,"%s(from %s:%d) %d bytes\n   :", tag, inet_ntoa(client->sin_addr), client->sin_port, len);
	else
		fprintf(fp,"%s %d bytes\n   :", tag, len);

	int i;
	for(i=0; i<len; i++) {
		fprintf(fp, "%x ", data[i]);
	}
	fprintf(fp, "\n");
	fclose(fp);
}
